package cubelabs.nexus.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.opentok.api.OpenTokSDK;
import com.opentok.api.OpenTokSession;
import com.opentok.api.constants.RoleConstants;

import cubelabs.nexus.dao.CategoryDAO;
import cubelabs.nexus.dao.CounsellingEventDAO;
import cubelabs.nexus.dao.CounsellingSessionDAO;
import cubelabs.nexus.dao.ReviewDAO;
import cubelabs.nexus.dao.UserCategoryDAO;
import cubelabs.nexus.dao.UserDAO;
import cubelabs.nexus.domain.CategoryDTO;
import cubelabs.nexus.domain.CounselRequestDTO;
import cubelabs.nexus.domain.CounsellingEventReview;
import cubelabs.nexus.domain.SessionData;
import cubelabs.nexus.domain.UserDTO;
import cubelabs.nexus.entity.Category;
import cubelabs.nexus.entity.CounsellingEvent;
import cubelabs.nexus.entity.CounsellingSession;
import cubelabs.nexus.entity.CounsellingEventStatus;
import cubelabs.nexus.entity.User;
import cubelabs.nexus.entity.UserCategory;
import cubelabs.nexus.utils.GenericUtils;

@Service
public class NexusService {

	@Autowired
	private UserDAO userDAO;
	
	@Autowired
	private CategoryDAO categoryDAO;
	
	@Autowired
	private CounsellingEventDAO counsellingEventDAO;
	
	@Autowired
	private UserCategoryDAO userCategoryDAO;
	/*@Autowired
	private CounsellingAcceptorDAO counsellingAcceptorDAO;
	*/
	@Autowired
	private ReviewDAO reviewDAO;

	@Autowired
	private CounsellingSessionDAO counsellingSessionDAO;
	
	@Transactional
	public User fetchUserById(Long userId){
		User user = null;
		if(userId != null){
			user = userDAO.findById(userId, false);
			user.getCategories();
		}
		return user;
	}
	
	@Transactional
	public List<UserDTO> fetchUsersByCategoryId(Long categoryId, User sessionUser){
		List<User> users= null;
		Category category = null;
		if(categoryId != null){
			category = categoryDAO.findById(categoryId, false);
			users = category.getUsers();
		}
		long sessionUserId = -1 ;
		
		if(sessionUser != null){
			sessionUserId = sessionUser.getId();
		}
		
		List<UserDTO> userDTOList = null;
		if(users != null && users.size()> 0){
			userDTOList = new ArrayList<UserDTO>();
			for(User user:users){
				UserDTO userDTO = GenericUtils.getUserDTO(user);
				if(sessionUserId != userDTO.getId())
					userDTOList.add(userDTO);
			}
			
		}
		return userDTOList;
	}

	@Transactional
	public Boolean isUserInCategory(Long categoryId, Long userId){
		
		UserCategory userCategory = userCategoryDAO.findByCategoryAndUser(categoryId, userId);
		if(userCategory != null)
			return false;
		
		return true;
	}
	
	
	
	
	@Transactional
	public List<Category> findAllCategories() {
		return categoryDAO.findAll();
	}
	
	@Transactional
	public List<CounsellingEventReview> findReviewByUserId(Long userId) {
		List<CounsellingEventReview> counsellingEventReviews = null;
		User user = fetchUserById(userId);
		if(user != null){
			List<CounsellingEvent> counsellingEvents = counsellingEventDAO.findByCounsellingAcceptorId(userId);
			if(counsellingEvents != null && counsellingEvents.size() > 0){
				counsellingEventReviews = new ArrayList<CounsellingEventReview>();
				for(CounsellingEvent counsellingEvent : counsellingEvents){
					CounsellingEventReview counsellingEventReview = new CounsellingEventReview();
					counsellingEventReview.setDescription(counsellingEvent.getReview());
					counsellingEventReview.setRating(counsellingEvent.getRating());
					counsellingEventReview.setUser(counsellingEvent.getFrmUser());
					counsellingEventReviews.add(counsellingEventReview);
				}
			}
		}
		return counsellingEventReviews;
	}

	@Transactional
	public List<CounselRequestDTO> findCounselRequestsByUserId(Long userId) {
		List<CounselRequestDTO> counselRequestDTOList = new ArrayList<CounselRequestDTO>();
		List<CounsellingEvent> counsellingEvents = counsellingEventDAO.findByToUser(userId);
		for(CounsellingEvent counsellingEvent : counsellingEvents){
			CounselRequestDTO counselRequestDTO = new CounselRequestDTO();
			counselRequestDTO.setDescription(counsellingEvent.getDiscription());
			counselRequestDTO.setEndTime(counsellingEvent.getEnd());
			counselRequestDTO.setStartTime(counsellingEvent.getStart());
			counselRequestDTO.setId(counsellingEvent.getId());
			counselRequestDTOList.add(counselRequestDTO);
		}
	/*	List<CounselRequestDTO> counselRequestDTOList = null;
		if(user != null){
			counsellingAcceptorList = counsellingAcceptorDAO.findPendingRequests(user);
			if(counsellingAcceptorList != null && counsellingAcceptorList.size() > 0){
				counselRequestDTOList = new ArrayList<CounselRequestDTO>();
				for(CounsellingAcceptor counselAcceptor : counsellingAcceptorList){
					CounselRequestDTO counselRequestDTO = new CounselRequestDTO();
					CounsellingEvent counsellingEvent = counselAcceptor.getCounsellingEvent();
					counselRequestDTO.setDescription(counsellingEvent.getDiscription());
					counselRequestDTO.setEndTime(counsellingEvent.getEnd());
					counselRequestDTO.setStartTime(counsellingEvent.getStart());
					counselRequestDTO.setId(counsellingEvent.getId());
					counselRequestDTOList.add(counselRequestDTO);
				}
			}
		}
	*/	
		return counselRequestDTOList;
	}

	@Transactional
	public User fetchUserByEmail(String email) {
		User user = null;
		if(email != null){
			user = userDAO.findByEmail(email);
		}
		return user;	
	}

	@Transactional
	public User createUser(UserDTO userDTO) {
		User user = copyUserToUserDTO(userDTO);
		userDAO.makePersistent(user);
		userDTO.setId(user.getId());
		return user;
	}

	@Transactional
	public User updateLoginTime(User user) {
		user.setLastLogin(new Date());
		userDAO.makePersistent(user);
		return user;
	}
	
	public User copyUserToUserDTO(UserDTO userDTO){
		User user = new User();
		user.setEmail(userDTO.getEmail());
		user.setImagePath(userDTO.getImagePath());
		user.setName(userDTO.getName());
		user.setActive(true);
		user.setLastLogin(new Date());
		return user;
	}

	@Transactional
	public void createCategory(CategoryDTO categoryDTO) {
		Category category = new Category();
		category.setName(categoryDTO.getName());
		category.setIconPath(categoryDTO.getIconPath());
		categoryDAO.makePersistent(category);
		categoryDTO.setId(category.getId());
	}

	@Transactional
	public UserCategory addUserToCategory(Long categoryId, Long userId) {
		Category category = categoryDAO.findById(categoryId, false);
		User user = userDAO.findById(userId, false);
		UserCategory userCategory = new UserCategory();
		userCategory.setUser(user);
		userCategory.setCategory(category);
		userCategoryDAO.makePersistent(userCategory);
		return userCategory;
	}

	@Transactional
	public void createEvent(CounsellingEvent counsellingEvent) {
		//counsellingAcceptorDAO.makePersistent(counsellingEvent.getCounsellingAcceptor());
		counsellingEventDAO.makePersistent(counsellingEvent);
		//counsellingEventDAO.makePersistent(counsellingEvent);
	}

	@Transactional
	public CounsellingSession saveCounsellingSession(Long counselEventId) {
		CounsellingSession counsellingSession = new CounsellingSession();
		
		OpenTokSDK openTokSDK = new OpenTokSDK(21313161, "2c819ea062cc6557e618a4de655bcdce9e33d4f4");
		try {
			String sessionId = openTokSDK.create_session().session_id;
			String token = openTokSDK.generate_token(sessionId);
			
			counsellingSession.setSessionId(sessionId);
			counsellingSession.setToken(token);
			
			counsellingSession.setCounsellingEvent(counsellingEventDAO.findById(counselEventId,false));
			
			counsellingSession.setApiKey(21313161);
			counsellingSession.setModeratorToken(openTokSDK.generate_token(sessionId, RoleConstants.MODERATOR));
			counsellingSession.setSubscriberToken(openTokSDK.generate_token(sessionId, RoleConstants.SUBSCRIBER));
			counsellingSession.setPublisherToken(openTokSDK.generate_token(sessionId, RoleConstants.PUBLISHER));
		}catch(Exception exception){
			exception.printStackTrace();
		}
		return counsellingSessionDAO.makePersistent(counsellingSession);
	}

	@Transactional
	public SessionData fetchSession(Long counselEventId) {
		CounsellingSession counsellingSession = counsellingSessionDAO.findByCounselEvent(counselEventId);

		if(counsellingSession != null){
		SessionData sessionData = new SessionData();
		sessionData.setApiKey(21313161);
		sessionData.setModeratorToken(counsellingSession.getModeratorToken());
		sessionData.setPublisherToken(counsellingSession.getPublisherToken());
		sessionData.setSessionId(counsellingSession.getSessionId());
		sessionData.setSubscriberToken(counsellingSession.getSubscriberToken());
		sessionData.setToken(counsellingSession.getToken());
		return sessionData;
		}else
			return null;
	}

	@Transactional
	public SessionData stopSession(Long counselEventId) {
		CounsellingEvent counsellingEvent = counsellingEventDAO.findById(counselEventId, false);
		SessionData sessionData = new SessionData();		
		if(counsellingEvent != null){
			counsellingEvent.setCounsellingEventStatus(CounsellingEventStatus.Closed);
			CounsellingSession counsellingSession = counsellingSessionDAO.findByCounselEvent(counselEventId);
			if(counsellingSession != null){
				sessionData.setApiKey(21313161);
				sessionData.setModeratorToken(counsellingSession.getModeratorToken());
				sessionData.setPublisherToken(counsellingSession.getPublisherToken());
				sessionData.setSessionId(counsellingSession.getSessionId());
				sessionData.setSubscriberToken(counsellingSession.getSubscriberToken());
				sessionData.setToken(counsellingSession.getToken());
			}
		}
		return sessionData;
	}
}
